#ifndef SLOTGUTS_H
#define SLOTGUTS_H

#pragma warning (disable:4786)
#pragma warning (disable:4800) // CSN-12948 - Upgrade to VS2012

#include <list>
#include <vector>

#include "lib.h"
#include "slotspin.h"
#include "subgamedata.h"
#include "featuredata.h"
#include "tracksql.h"
#include "SlotProbabilityTable.h"

typedef vector<uint32> FiveReelDebugStops;

typedef vector<FiveReelDebugStops> DebugStops;

// CGC: payout for an all pays slot
typedef struct sALL_PAYS_PAYOUT {
			uint8 Icon;
			int32 Positions;
			uint8 WinType;
			uint8 Multiplier;
} ALL_PAYS_PAYOUT;

class Info
{
public:
    Info()
    {
        machineID = 0;
        machineSubID = 0;
        betperline = 0;
        forMoney = 0;
        compFactor = 0;
        balance = 0;
    }

	String			login;
    PID				pid;
    SESSIONID		sessionId;
    uint8			machineID;
    uint16          machineSubID;
    int32           betperline;
    bool8			forMoney;
    int32           compFactor;
    int32           balance;
};

typedef Info*   pInfo;

class SlotGameDenomination
{
public:

    SlotGameDenomination(uint16 machineSubID, uint16 creditValue, bool8 isDefault)
    {
        m_machineSubID = machineSubID;
        m_creditValue = creditValue;
        m_isDefault = isDefault;
    }
 
    uint16          m_machineSubID;
    uint16          m_creditValue;
    bool8           m_isDefault;
};

/**
 * @brief a class defining the slot reel icon.
 * 
 */
struct SlotIcon
{
    public:
        /**
         * @brief The reel for this icon.
         */
        uint8    reelid;

        /**
         * @brief The position on the reel.
         */
        uint8    position;

        /**
         * @brief The id of the icon it represents.
         */
        uint8    iconid;

        /**
         * @brief The probability weighting
         */
        int64   weight;

        /**
         * @brief the name as a string.
         */
        char *iconName;

};


/**
 * @brief a class defining the slot payline position.
 * 
 */
struct SlotPaylinePosition
{
    public:
        /**
         * @brief The payline index.
         */
        uint8    payline;

        /**
         * @brief The reel for this payline position.
         */
        uint8    reelid;

        /**
         * @brief The offset position.
         */
        uint8    wheelposition;

};

/**
 * @brief a class defining the slot payout line.
 */
struct SlotPayout
{
    public:
        /**
         * @brief The index of this payline.
         */
        uint8    payoutTypeId;

        /**
         * @brief The bet amount associated with this payline.
         */
        uint8    betAmount;

        /**
         * @brief The string name of this payout.
         */
        char *payoutName;

        /**
         * @brief The amount this line pays in cents.
         */
        int32 payoutAmount;
};


class DebugStopFuncBase;
typedef std::map< int32, DebugStopFuncBase* > DebugFunctionMap;


/**
 * @brief base class for all slots guts.
 * 
 * This is the base class for all slots guts.  It is capable
 * of loading an instance of itself and instantiating a complete
 * guts from the database.
 * 
 */
class SlotGuts
{
	public:

        #include "SlotsBaseCommon.h"

        /**
         * @brief The slot payouts list type.
         */
        typedef vector<const SlotPayout *> SlotPayColumn;

        /**
         * @brief The slot reels list type.
         */
        typedef vector<const SlotIcon *> SlotReel;

        typedef vector<SlotProbabilityTable*> SlotProbabilityTableVector;

        /**
         * @brief Public Constants used by this class.
         */
        enum PUB_CONSTANTS
        {
            /**
             * @brief the max icon name length.
             */
            ICON_NAME_LEN = 64,
            FEATURE_GAME_CAP = 40000
        };

        /**
         * @brief Create an instance of a slot guts.
         * @param machid the machine id.
         * @return a slot guts pointer.
         */
        static SlotGuts *createGuts(uint8 machid);

        /**
         * @brief Base destructor.
         * 
         * @param   gutsid the guts identifier.
         */
		virtual ~SlotGuts();

        /**
         * @brief Get the game number these spins refer to.
         * @return The game number or 0 if there is no meta game.
         */
        int64 getReferenceGameNum();

        void setReferenceGameNum(int64 nGameNum);

        int32 getJackpotAmount();

        void setJackpotAmount(int32 nJackpotAmount);

		bool8 shouldSaveGameData();

        /**
         * @brief Check the bet for validity.
         * @return The numb
         */
		virtual void *getCustomData();

        /**
         * @brief create a spin then complete it.
         * @param bet the bet in cents.
         * @param multibankBet the bet in cents.
         * @param lineCount the number of lines bet.
         * @param bonusGame the bonus game identifier.
         */
		virtual SlotSpin *spin(uint8 bet, int32 multibankBeCentst, uint8 lineCount, uint8 bonusGame, bool8 bAutoplay);

        /**
         * @brief create a spin then complete it.
         * @param bet the bet in cents.
         * @param lineCount the number of lines bet.
         * @param bonusGame the bonus game identifier.
         */
		virtual SlotSpin *spin(int32 multibankBetCents, uint8 lineCount, uint8 bonusGame,bool8 bAutoplay);

        /**
         * @brief Iterate the lines played and determine winners.
         * @param spin the slot spin.
         * @see classifyStops
         */
        virtual void classifyResult(SlotSpin *spin);

        /**
         * @brief See if a particular icon configuration is a winner.
         * @param stops the array of icons.
		 * @param bet the amount of the bet
		 * @param line the line for this stop - useful for multi-line slots
         */
        virtual void classifyStops(SpinLine* spinline, uint8 *stops, uint8 bet, uint8 line, uint8& rtnresult, uint8& multiplier);

        /**
         * @brief See if a spin has scatter winners
         * @param spin the slot spin
         */
        virtual void classifyScatters(SlotSpin *spin){};

        /**
         * @brief Get the guts id.
         * @return The id for this guts.
         */
		int32 getGutsId();

        uint8 getGameModeId() const;
        void  setGameModeId(uint8 m_nGameModeId);

        /**
         * @brief Get the guts name.
         * @return The name for this gut.
         */
		void getGutsName(char* name);

        /**
         * @brief Get the guts name.
         * @return The name for this gut.
         */
        void getLocale(localCurrency* pLocalCurrency);

        /**
         * @brief Set the guts id.
         * @param gutsId The id for this guts.
         */
		void setGutsId(int32 gutsId);

        /**
         * @brief Get the player id.
         * @return the player id.
         */
		const PID& getPid();

        /**
         * @brief Get the jackpot id.
         * @return The id for this jackpot.
         */
		int32 getJackpotId();

        /**
         * @brief Set the jackpot id.
         * @param jackpotId The id for this jackpot.
         */
		void setJackpotId(int32 jackpotId);

        /**
         * @brief Set the jackpot hit odds
         * @param jackpotHitOdds The odds for this jackpot
         */
		void setJackpotHitOdds(int32 jackpotHitOdds);

        /**
         * @brief Check the for money flag.
         * @returns true if for money.
         */
        bool8 isForMoney();

        /**
         * @brief Check the progressive flag.
         * @returns true if progressive is on.
         */
        bool8 isProgressive();

        /**
         * @brief Set the progressive flag.
         * @param progressive the new flag setting.
         */
        void setProgressive(bool8 progressive);

        /**
         * @brief Get the progressive contribution for the current spin.
         * @returns false to allow the stored procedures to calculate the
		 * contribution automatically.
         */
		virtual bool8 getProgressiveContribution(int32 nBetPerLine, int32 nLineCount, int32& nContribution, int32& nContributionFractionalCents);

        /**
         * @brief Set the state of the machine to bonus game.
         * 
         * Set the state of the machine to bonus game.  For the base class
         * this method does nothing.
         */
		virtual bool8 processClientData(uint8 dataType, int32 dataCount, int32 *data);

		// CSN-5756: with the new korean team game (Saturn GP) we need to support fixed jackpot amounts
		virtual int32 getFixedJackpotValue();

        /**
         * @brief Get the number of reels
         * @brief The game mode ID for which we want the reels
         * @returns The number of reels for this guts.
         */
        uint8 getReelCount(uint8 nGameModeId = 0) const;

        virtual uint8 getRowCount();

        /**
         * @brief Get the size of the reel.
         * @param reelid the reel number.
         * @returns The number of icons for this reel.
         */
        uint8 getIconCount(uint8 nGameModeId, uint8 reelid) const;

        /**
         * @brief Get the icons
         * @param reel the reel number
         * @param icons an array of SlotIcons (allocated by caller).
         * Get the icons for a specific reel.
         */
        const SlotReel *getSlotReel(uint8 nGameModeId, uint8 reelid);

        /**
         * @brief Reset the reels.
         */
        void clearWheelhouse();

        /**
         * @brief add an icon.
         * @param gamemodeid the game mode for which these reels are valid.
         * @param reelid the reel number.
         * @param iconid the id of the icon.
         * @param reelposition the location of the icon on the reel.
         * @param weight the number needed to acheive this location on the reel.
         * @param iconName the null terminated string description of the icon.
         */
        void addIcon(uint8 gamemodeid, uint8 reelid, uint8 iconid, uint8 reelposition, int64 weight, const char *iconName);

        /**
         * @brief Get the number of payouts.
         * @returns The number of payouts for that bet.
         */
        uint8 getPayoutCount() const;

        /**
         * @brief Get the payouts in a bet column.
         * @param bet the bet amount in coins.
         */
        const SlotPayColumn *getPayColumn();

        /**
         * @brief Reset the payouts.
         */
        void clearPayTable();

        /**
         * @brief add a payout.
         * @param payoutTypeId the index of the payout.
         * @param payoutName the null terminated string name for this payout.
         * @param payoutAmount the amount of the payout in credits.
         */
        void addPayout(uint8 payoutTypeId, const char *payoutName, int32 payoutAmount);


        /**
         * @brief Reset the paylines.
         */
        void clearPaylines();

        /**
         * @brief get the number of paylines.
         * @return the number of paylines.
         */
        uint8 getPaylineCount();

        /**
         * @brief get the position of the specified payline.
         * @param paylineid the payline index.
         * @param reelid the reel index
         * @return the payline position.
         */
        uint8 getPaylinePosition(uint8 paylineid, uint8 reelid);

        /**
         * @brief add a payline.
         * @param paylineid the payline index.
         * @param reelid the reel index.
         * @param wheelposition the reel offset.
         */
        void addPayline(uint8 paylineid, uint8 reelid, uint8 wheelposition);

		void clearProbabilityTables();
		void addProbabilityTable( int32 nTableID );
		SlotProbabilityTable* getProbabilityTable( int32 nTableID ) const;
        void addProbabilityTableEntry( int32 nTableID, uint32 nMaxWeightForValue, int32 nValue );
		int32 getRandomValueFromProbabilityTable( int32 nTableID = 0 ) const;

        /**
         * @brief Get the machine id.
         * @returns the machine id.
         */
        uint8 getMachId();

        /**
         * @brief Get the subgame data.
         * @returns a read-only pointer to the subgame data array.
         */
        SubGame *getSubGame();

        /**
         * @brief get the subgame data size.
         * @return the subgame data size.
         */
		int32 getSubGameSize();

        /**
         * @brief Get the top payline
         * @return the maximum payout.
         */
        const SlotPayout *getMaxPayout();

        /**
         * @brief Get the specified payline
         * @param payouttypeid the index of the payline.
         * @return the payout.
         */
        const SlotPayout *getPayout(uint8 payouttypeid) const;

        /**
         * @brief Get the specified icon
         * @param gamemodeid the game mode
         * @param reelid the reel number.
         * @param position the reel position.
         * @return the icon.
         */
        virtual const SlotIcon *getIcon(uint8 gamemodeid, uint8 reelid, uint8 position) const;

        /**
         * @brief Load the guts
         * @param info the information pointer indicating the type of machine to load.
         * @return TRUE if the guts loaded properly
         */
		virtual bool8 load(Info *info);

        /**
         * @brief Save the subgame data to the database.
         */
		virtual void saveSubGameData();

        /**
         * @brief Load the subgame data from the database.
         */
		virtual void loadSubGameData();

        /**
         * @brief Save the subgame data to the database in an archive table (persistent).
		 * Make sure the current game has been saved.  Only then can you get a valid gamenum.
		 * SlotGuts::saveGame () must get called before gamenum is valid
         * @param gamenum the game number for this game.
         */
		//virtual void archiveSubGameData(int64 gamenum);

//		virtual void loadFeatureData(Feature* feature);
//		virtual void saveFeatureData(Feature* feature);
		virtual void loadFeatureData();
		virtual void saveFeatureData();
		virtual void allocateFeatureData();
		virtual int32 getFeatureSize();
		virtual Feature * getFeature();

		virtual bool8 loadSavedGame();

        /**
         * @brief get a specific spin.
         * @param spinid the index of the desired spin.
         * @return pointer to a SlotSpin.
         */
        SlotSpin *getSlotSpin();

        /**
         *  Has the game been saved to the database?
         *  @return true if the game has been saved.
         */
		virtual bool8 getGameCanComplete();

        /**
         * @brief Save the bonus game information.
         * @return true if the save succeeds.
         */
		virtual bool8 saveBonusGames();

        /**
         * @brief Save the reel and payout information for each spin.
        * @return true if the save succeeds.
         */
		bool8 saveSpin();

        /**
         * @brief Save each spin.
        * @return true if the save succeeds.
         */
		virtual bool8 saveGame();

        /**
         * @brief complete each created slot spin.
         * @return True if the game completion succeeds.
         */
		bool8 completeGame();

        /**
         * @brief Get the info pointer.
         * @return the constant info pointer.
         */
        Info *getInfo();


        /**
         * @brief Check for a malfunction
         * @returns true if the machine has malfunctioned.
         */
        virtual bool8 isMalfunction();

        /**
         * @brief Reset the guts for a new game.
         */
        virtual void resetForNewGame();

        uint8 getDenominationCount() const;

        void clearDenominations();
        
        SlotGameDenomination*  getDenomination(uint8 nIndex);

        virtual void addDenomination(uint16 machineSubId, uint16 creditValue, bool8 isDefault);

        uint8 getWheelhouseCount();

        virtual int32 getFeatureGameCap() const;

		bool8 getMaxPayoutAwarded() const;
		void setMaxPayoutAwarded( bool8 bMaxPayoutAwarded = true );

        int32 getFreeSpins() const;

		virtual bool8 canSpin();
		virtual bool8 isBonusGameInProgress();

        /**
         * @brief Should the server log a warning when client data is recvd outside a spin
         */
		virtual bool8 warnOnClientDataWithoutSpin() const;

		virtual int32 getNumLinesBet();

		bool isThirdPartyGame() {return isThirdParty;}

#ifdef ALLOW_SPIN_TESTING
        bool8   canMakeSpinTestProgressiveBet() const { return m_bSpinTestAllowProgressiveBet; }
#endif

	protected:

		virtual void resetDataForNextSpin();

		bool getFeatureTriggered() const;
		void setFeatureTriggered( bool bTriggered );

		int32 getReelFeatureTriggerStep( int32 nReel ) const;
		void setReelFeatureTriggerStep( int32 nReel, int32 nStep );

		bool getReelAnticipation( int32 nReel ) const;
		void setReelAnticipation( int32 nReel, bool bAnticipation );

        /**
         *  Signal game complete
         *  @return game complete state
         */
		bool8 setGameCanComplete(bool8 isComplete);

        /**
         * @brief complete the already created spin.
         * @param spin the slot spin.
         */
		virtual void spin(SlotSpin *spin);

        /**
         * @brief Create a guaranteed winning spin.
         * @param bet the bet in cents.
         * @param bonusGame the bonus game identifier.
         */
        SlotSpin *makeWinningSpin(uint8 bet, uint8 bonusGame);

        /**
         * @brief Create a guaranteed winning spin.
         * @param spin the spin pointer.
         */
        void makeWinningSpin(SlotSpin *spin);

        /**
         * @brief Iterate the lines and determine if something has occurred that
         *        alters the actual values on the reel.
         * @param spin the slot spin.
         */
        virtual void preSpinClassifyResults(SlotSpin *spin);
        
        /**
         * @brief Iterate the lines and determine if something has occurred that
         *        alters the actual values on the reel.
         * @param spin the slot spin.
         */
        virtual void postSpinClassifyResults(SlotSpin *spin);
        
        /**
         * @brief Whether this game uses saved games.
         */
        virtual bool8 hasSavedGames(){return false;};


        /**
         * @brief Create an instance of a slot
         */
		SlotGuts();

        /**
         * @brief The collection of payouts (Internal version allows cleanup). 
         */
        typedef vector<SlotPayout *> ISlotPayColumn;

        /**
         * @brief The collection of pay columns.
         */
        typedef ISlotPayColumn* SlotPayTable;

        /**
         * @brief The collection of icons (Internal version allows cleanup).
         */
        typedef vector<SlotIcon *> ISlotReel;

        /**
         * @brief The collection of slot reels.
         */
        typedef vector<ISlotReel *> SlotWheelHouse;


        /**
         * @brief The collection of payline positions (or offsets).
         */
        typedef vector<SlotPaylinePosition *> SlotPaylineReel;

        /**
         * @brief The collection of payline reels.
         */
        typedef vector<SlotPaylineReel *> SlotPayline;

        typedef vector<SlotGameDenomination*> SlotGameDenominationVector;

        /**
         * @brief A vector of paylines.  Paylines hold reels.  Reels hold offsets.
         */

        SlotPayline m_paylines;

        /**
         * @brief A vector of pay columns.
         */
        SlotPayTable m_payTable;

        /**
         * @brief A vector of reels.
         */

        typedef vector<SlotWheelHouse*> SlotWheelHouseVector;
        
        SlotWheelHouseVector m_vecWheelHouse;

        SlotGameDenominationVector  m_vecDenominations;

        /**
         * @brief Check that the gutsid is valid.
         */
        virtual bool8 isValidGuts();

        /**
         * @brief Create an array of initialized subgame data.
         */
		virtual void allocateSubGameData();

        /**
         * @brief the machine id.
         */
        uint8 m_machid;

        /**
         * @brief Whether there is a subgame to load.
         */
        bool8 m_hasSavedGame;

        /**
         * @brief The subgame information.
         */
        SubGame *m_subGame;

		Feature*	m_feature;
	
        /**
         * @brief Malfunction short circuit.
         */
        bool8 m_hardMalfunction;

        /**
         * @brief Find the icon position.
         * @returns the position of the icon represented by this weight.
         */
        virtual uint8 findPositionByWeight(uint8 gamemodeid, int64 weight, uint8 reelid);

		/**
         * @brief Get a random array element - numElements should be a power of two for true random results
         * @returns an item between data[0] and data[numElements-1]
         */		
		int32 getRandomFromArray(int32* data, uint32 numElements);

        /**
         * @brief The slot spins.
         * @returns the position of the icon represented by this weight.
         */
        SlotSpin*     m_spin;

        /**
         * @brief the wheel position after applying the offset.
         * @param reelid the reel index.
         * @param position the original position on the reel.
         * @param offset the number of stops to look forward on the reel.
         */
        uint8 relativeWheelPosition(uint8 gamemodeid, uint8 reelid, uint8 position, uint8 offset) const;

        /**
         * @brief get the reel offset position for the payline.
         * @param paylineid the payline index.
         * @param reelid the reel index.
         */
        virtual SlotPaylinePosition *getPayline(uint8 paylineid, uint8 reelid);

        /**
         * @brief A pointer to the info structure.
         */
        Info *m_info;

        /**
         * @brief The id for this jackpot (if progressive).
         */
		int32 m_jackpotid;

        /**
         * @brief The id for this jackpot hit odds (if progressive).
         */
		int32 m_jackpotHitOdds;

        /**
         * @brief The progressives flag.
         */
		bool8 m_progressive;

        /**
         * @brief The game number all spins should be referning to.  Default is 0.
         */
        int64 m_referenceGameNum;

		
        virtual void getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId );

        virtual bool8 getRandomProgressiveJackpotResult(uint8 lineCount);

        virtual int32 getBaseChanceForRandomJackpot();

        uint32 getReelMaxWeight(uint8 nGameModeId, uint8 nReelId);

        void storeWheelView(SlotSpin* spin);

        int32 getTotalWin();
        void  setTotalWin(int32 totalWin);
		void  increaseTotalWin( int32 addWinnings );

        virtual void decrementFreeSpins(int32 numSpins = 1);
        virtual void incrementFreeSpins(int32 numSpins = 1);
		virtual void removeAllFreeSpins();

        void setBetPerLine( int32 betperline );
        int32 getBetPerLine();

        void setNumLinesBet( int32 numLinesBet );
        

		virtual int32 getBonusGameState() const;
		virtual void  setBonusGameState( int32 bonusGameState );

		BonusGame* addBonusGame(uint8 bonusgametype,uint8 bonusgameindex,int32 basepayoutamount,int32 totalmultiplier,int32 totalbonuspayoutamount,int32 freespins,int64 overridegamenum = 0,bool8 bSaved = false);
    
	protected:

        /**
         * @brief True if game is complete.
         */
		bool8 m_gameCanComplete;

        bool8 m_bCanResetForNewGame;

		SlotProbabilityTableVector m_probabilityTables;

        /**
         * @brief The id for this guts.
         */
		int32 m_gutsid;

        // Multi-cash/Progressives spin testing
        bool m_bSpinTestAllowProgressiveBet;


		//Debug Spins Functionality

		bool m_bDebugSpinsMode;

		// CGC 20100608. To indicate if it is a new game which works through the new casino API
		bool isThirdParty;

		DebugStops::size_type  m_nDebugSpinIndex;
		DebugStops m_debugReelStops;
		int32	m_debugSpinCount;	// Number of spins in the m_debugReelStops array


        virtual void processDebugStops( SlotSpin *spin );

        DebugFunctionMap  m_mapDebugFunctions;

        virtual void initDebugFunctionMap();
        void    addDebugStopFunction( int32 key, DebugStopFuncBase* func );

        enum
        {
			THIS_IS_A_FUNCTION			= 255,

			//This is the range of GENERATOR ids implemented in the base SlotGuts class (1-100)
            BEGIN_BASE_FUNCTION_RANGE	= 1,
            END_BASE_FUNCTION_RANGE		= 100,

			//This is the range of MODIFIER function ids implemented in the base SlotGuts class (101-200)
            BEGIN_BASE_MODIFY_NEXT_RESULT_FUNCTION_RANGE = 101,
            END_BASE_MODIFY_NEXT_RESULT_FUNCTION_RANGE = 200,

			//This is the range of GENERATOR ids available to subclasses (201-300)
            BEGIN_SUB_FUNCTION_RANGE	= 201,
            END_SUB_FUNCTION_RANGE		= 300,

			//This is the range of MODIFIED function ids available to subclasses (301-400)
            BEGIN_SUB_MODIFY_NEXT_RESULT_FUNCTION_RANGE = 301,
            END_SUB_MODIFY_NEXT_RESULT_FUNCTION_RANGE = 400,
        };

		enum
		{
			EVT_DEBUG_FUNCTION_FEATURE_EXIT = BEGIN_BASE_FUNCTION_RANGE,
			EVT_DEBUG_FUNCTION_LOSER_SPIN,
			EVT_DEBUG_FUNCTION_RANDOM_SPIN,
			EVT_DEBUG_FUNCTION_RANDOM_JACKPOT,

			EVT_DEBUG_FUNCTION_RANDOM_JACKPOT_NEXT = BEGIN_BASE_MODIFY_NEXT_RESULT_FUNCTION_RANGE,
			EVT_DEBUG_FUNCTION_RIGHT_TO_LEFT
		};

		/**
		 * @brief Enum containing the MatchID per game
		 * 
		 * This is a MUST in order to get a proper list 
		 * with available/used MatchID values.
		 * 
		 */
		enum  {
			MACHID_RONIN				=	1,
			MACHID_CLEOSGOLD			=	2,
			MACHID_AZTECSTREASURE		=	3,
			MACHID_GOLDBEARD			=	4,
			MACHID_CAESARSEMPIRE		=	5,
			MACHID_DIAMONDDOZEN			=	6,
			MACHID_PRINCEOFSHERWOOD		=	7,
			MACHID_VIKINGSVOYAGE		=	8,
			MACHID_LIONSLAIR			=	9,
			MACHID_MISTERMONEY			=	10,
			MACHID_DERBYDOLLARS			=	11,
			MACHID_TIGERTREASURES		=	12,
			MACHID_SUNKENTREASURE		=	13,
			MACHID_MERMAIDQUEEN			=	14,
			MACHID_HILLBILLIES			=	15,
			MACHID_FRUITFRENZY			=	16,
			MACHID_TALLYHO				=	17,
			MACHID_RAINDANCE			=	18,
			MACHID_GREENLIGHT			=	19,
			MACHID_REDSANDS				=	20,
			MACHID_TRIPLETOUCAN			=	21,
			MACHID_FUNKYMONKEY			=	22,
			MACHID_ENCHANTEDGARDEN		=	23,
			MACHID_VICTORY				=	24,
			MACHID_ALADDINSWISHES		=	25,
			MACHID_CRYSTALWATERS		=	26,
			MACHID_GOLDENGLOVE			=	27,
			MACHID_INCANGODDESS			=	29,
			MACHID_OUTTATHISWORLD		=	30,
			MACHID_PARADISEDREAMS		=	31,
			MACHID_ACHILLES				=	32,
			MACHID_HONEYTOTHEBEE		=	33,
			MACHID_REALMOFRICHES		=	35,
			MACHID_PENGUINPOWER			=	36,
			MACHID_TREASURECHAMBER		=	37,
			MACHID_PARISBEAUTY			=	38,
			MACHID_FAMEANDFORTUNE		=	39,
			MACHID_BIGSHOT				=	40,
			MACHID_JACKPOTPINATAS		=	41,
			MACHID_DIRTYMARTINI			=	82,
			MACHID_WITCHESANDWIZARDS	=	96,
			MACHID_DRAGONS				=	102,
			MACHID_HERCULES				=	104,
			MACHID_HYDROHEAT			=	97,
			MACHID_REELBLOOD			=	98,
			MACHID_ARES					=	103,
			MACHID_INVASION				=	105,
			MACHID_ELLUCHADOR			=	99,
			MACHID_TEACUPDRAGON			=	100,
			MACHID_INDIANAJOAN			=	101,
			MACHID_CASHMONEYMERMAIDS	=	106,
			MACHID_JACKTHERIPPER		=	107,
			MACHID_DJMOOCOW				=	108,
			MACHID_DESERTKINGDOM		=   109,
			MACHID_BIGMONEYBIGFOOT		=   110,
			MACHID_QUEEONOFKINGS		=   111,
			MACHID_BIRDSOFFURY			=   112,
			MACHID_DINOISLAND			=   113,
			MACHID_GLADIATORWARS		=   114,
			MACHID_SIXSHOTSHOWDOWN		=   115,
			MACHID_DRAGONPRINCESS		=   116,
			MACHID_SNOWWHITE			=   117,
			MACHID_ZOMBIES_CHEERLEADERS	=   118,
			MACHID_FOOTBALL_FRENZY		=   119,
			MACHID_ZOMBIES_CHEERLEADERS2=   120,
			MACHID_TREASUREISLAND		=	160,
			MACHID_SATURNGP				=   161,
			MACHID_FIELDOFGREEN			=	200
			// add new machid for game here!
		}; 

		//base functions

		void DebugStops_FeatureExit( SlotSpin *spin);

		void DebugStops_Loser( SlotSpin *spin = NULL );
		virtual void Debug_SetLoserStops( uint8* pStops );

		void DebugStops_RandomSpin( SlotSpin * spin);

		bool m_bForceRandomJackpot;
		void DebugStops_RandomJackpot( SlotSpin *spin);

		void DebugStops_RightToLeft( SlotSpin *spin);

		uint8 DebugStops_findStopWithIconID( uint8 reelid, uint8 iconid, uint8 paylineid );
		uint8 DebugStops_findStopIconID( uint8 reelid, uint8 position, uint8 paylineid );


		//end base functions

};


class DebugStopFuncBase
{
	protected:
    SlotGuts* m_guts;

	public:
    DebugStopFuncBase( SlotGuts* guts )
        : m_guts( guts )
    {
    }
    
    virtual void operator() ( SlotSpin *spin = NULL )
    {
    }
};

template <class derived>
class DebugStopFunc : public DebugStopFuncBase
{
	public:
    typedef	void (derived::*DEBUG_STOP_PROC)( SlotSpin *spin );

	private:
    DEBUG_STOP_PROC m_proc;
    
	public:    
    DebugStopFunc()
        : DebugStopFuncBase( NULL ), m_proc( NULL )
    {
    }
    
    DebugStopFunc( SlotGuts* guts, DEBUG_STOP_PROC proc)
        : DebugStopFuncBase( guts ), m_proc( proc )
    {
    }
    
    void operator() ( SlotSpin *spin )
    {
        (((derived*)(m_guts))->*m_proc)( spin );
    }

    void registerStopFunction( derived* pThis, DEBUG_STOP_PROC proc )
    {
        m_guts = pThis;
        m_proc = proc;
    }
};

template <class derived, class Argtype>
class DebugStopFunc1Arg : public DebugStopFuncBase
{
	public:
    typedef	void (derived::*DEBUG_STOP_PROC)( Argtype a, SlotSpin *spin );

	private:
    DEBUG_STOP_PROC m_proc;
    Argtype         m_arg;
    
	public:    
    DebugStopFunc1Arg()
        : DebugStopFuncBase( NULL ), m_proc( NULL ), m_arg(NULL)
    {
    }
    
    DebugStopFunc1Arg( SlotGuts* guts, DEBUG_STOP_PROC proc, Argtype argval)
        : DebugStopFuncBase( guts ), m_proc( proc ), m_arg( argval )
    {
    }
    
    void operator() ( SlotSpin *spin )
    {
        (((derived*)(m_guts))->*m_proc)( m_arg, spin );
    }

    void registerStopFunction( derived* pThis, DEBUG_STOP_PROC proc, Argtype argval )
    {
        m_guts = pThis;
        m_proc = proc;
        m_arg = argval;
    }
};

#if _MSC_VER>=1300
	template<class derived>
	std::pair<int32, DebugStopFuncBase*>
	MakeDebugFunc( derived* pThis, int32 key, typename DebugStopFunc<derived>::DEBUG_STOP_PROC proc )
	{
		return make_pair( key, new DebugStopFunc<derived>( pThis, proc ) );
	};
#endif

#endif // SLOTGUTS_H
